#pragma once
#include "Character.h"
#include "Util.h"
#include <set>

class Food;
class LockedObstacle;
class Scroll;
class RangedWeapon;

class Player : public Character {
protected:
	int m_satiation;
	std::set<Talent> m_talents;
	std::set<Tile*> m_visibleTiles;
	void logCombat(Character* enemy, bool nothing = false, bool hit = true, bool blocked = false, int damage = 0, bool crit = false, bool flame = false, bool envy = false, bool lust = false);
	bool removeStatusEffect(StatusEffect effect);
	void kick(GameObject* o, int x = 0, int y = 0);
	bool openDoor(Door* door);
	void giveExperience(int exp);
	void gatherResource(Resource* resource, Tool* tool);
	void moveToNewTile(int x, int y);
	void logReload(RangedWeapon* weapon, bool noAmmo = false) const;
public:
	Player(PlayerType type);
	Player(std::ifstream& file);
	~Player();
	void render(float x, float y);
	bool move(int x, int y);
	bool equip(EquipmentLocation location, Item* item, bool takeTurn = true);
	bool unequip(EquipmentLocation location);
	Item* drop(int index);
	Item* drop(Item* item);
	bool pickUp(Item* item);
	float getHealthPercent() const;
	int getCurrentHealth() const;
	int getMaxHealth() const;
	void changeStat(Stat stat, int mod);
	bool dealDamage(int damage);
	void modifyTurnCounter(int mod);
	SatiationStatus getSatiationStatus() const;
	bool quaff(Potion* potion);
	void heal(int amount);
	bool poison(int damage);
	void logDetails(TextLog& log) const;
	bool addStatusEffect(StatusEffect effect, int power);
	void doKick(int x, int y);
	void logTrap(TrapType trap, bool hit = true, int damage = 0);
	void eat(Food* food, bool inInventory = true);
	void unlockLock(LockedObstacle* lock, int shouldLock = 1);
	void readScroll(Scroll* scroll, Item* item = NULL);
	std::string getName() const;
	void addTalent(Talent talent);
	bool hasTalent(Talent talent) const;
	const std::set<Talent>& getTalents() const;
	void trainSkill(Skill skill, float amount);
	void calculateFOV();
	void save(std::ofstream& file) const;
};

inline float Player::getHealthPercent() const {return Util::normalize(float(m_currentHealth) / float(m_maxHealth));}
inline int Player::getCurrentHealth() const {return m_currentHealth;}
inline int Player::getMaxHealth() const {return m_maxHealth;}
inline bool Player::hasTalent(Talent talent) const {return m_talents.count(talent) > 0;}
inline const std::set<Talent>& Player::getTalents() const {return m_talents;}
